package com.ttn.common.core.util;

import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.function.Supplier;


@Slf4j
public class Null {

    public static final <T> T of(Supplier<T> expr, Supplier<T> defaultValue) {
        try {
            T result = expr.get();

            if (result == null) {
                return defaultValue.get();
            }
            return result;
        } catch (NullPointerException | IndexOutOfBoundsException e) {
            return defaultValue.get();
        } catch (Exception e) {
            log.error("ObjectHelper get error.", e);
            throw new RuntimeException(e);
        }
    }

    public static final <T> T of(Supplier<T> expr, T defaultValue) {
        Supplier<T> defaultValues = () -> defaultValue;
        return of(expr, defaultValues);
    }

    public static final <T> T of(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> null;
        return of(expr, defaultValues);
    }

    public static final <T> T ofString(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) "";
        return of(expr, defaultValues);
    }

    public static final <T> T ofList(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) Collections.EMPTY_LIST;
        return of(expr, defaultValues);
    }

    public static final <T> T ofSet(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) Collections.EMPTY_SET;
        return of(expr, defaultValues);
    }

    public static final <T> T ofMap(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) Collections.EMPTY_MAP;
        return of(expr, defaultValues);
    }

    public static final <T> T ofBool(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) Boolean.FALSE;
        return of(expr, defaultValues);
    }

    public static final <T> T ofInt(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) new Integer(0);
        return of(expr, defaultValues);
    }

    public static final <T> T ofDouble(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) new Double(0.0D);
        return of(expr, defaultValues);
    }


    public static final <T> T ofLong(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) new Long(0L);
        return of(expr, defaultValues);
    }

}
